import { Bounds } from "leafer-ui";
import { BlackType, DirectionType, MoveKeyType } from ".";
import { Bullet } from "./bullet";
import { AllMoveDirectionBlack } from "./allMoveDirectionBlack";
import { tankGroup } from "./tankGroup";
import { StaticBlack } from "./staticBlack";
import { TankProps } from "./tankProps";
import { sprite } from "./Sprite";
export const directionMap = {
  top: 0,
  right: 90,
  down: 180,
  left: 270,
};

export function throttle(func, delay) {
  let lastExecTime = 0;

  return function () {
    const now = Date.now();
    if (now - lastExecTime >= delay) {
      func.apply(this, arguments);
      lastExecTime = now;
    }
  };
}

const ReverseKey: { [key: string]: DirectionType } = {
  top: "down",
  down: "top",
  left: "right",
  right: "left",
};

export class Tank extends AllMoveDirectionBlack {
  #attackInterval = 400; // 攻击间隔
  stateProps: Map<string, number> = new Map();
  health = 1; // 生命
  constructor({
    x,
    y,
    width,
    height,
    targter,
    speed,
    moveKey,
    direction,
    id,
  }: Omit<BlackType, "isRadiusPoint"> & {
    speed: number;
    moveKey: MoveKeyType;
    isRadiusPoint?: boolean;
    direction: DirectionType;
    id?: string;
  }) {
    super({
      x,
      y,
      width,
      height,
      targter,
      speed,
      isRadiusPoint: true,
      moveKey,
      id,
    });
    tankGroup.addTank(this);
    this.orientation(direction);
    this.actionDirection = null;
  }
  // 朝向
  direction: DirectionType = "top";
  forbidDirection: DirectionType | null = null;
  #keyConvert(code) {
    let codeKey: DirectionType | null = null;
    switch (code) {
      case this.moveKey.top:
        codeKey = "top";
        break;
      case this.moveKey.down:
        codeKey = "down";
        break;
      case this.moveKey.left:
        codeKey = "left";
        break;
      case this.moveKey.right:
        codeKey = "right";
        break;
      case this.moveKey.enter:
        this.attack();
        break;
    }
    return codeKey;
  }
  // 移动
  updateActionDirection(code) {
    const codeKey = this.#keyConvert(code);
    this.forbidDirection = null;
    if (!codeKey) return;
    this.actionDirection = codeKey;
    if (this.direction !== codeKey) this.orientation(codeKey as DirectionType);
  }
  clearActionDirection(code: string): void {
    const codeKey = this.#keyConvert(code);
    if (this.actionDirection === codeKey) this.actionDirection = null;
  }

  remove() {
    this.targter.remove();
    sprite.remove(this.id);
    this.status = false;
    tankGroup.deleteTank(this.id);
  }
  // 被攻击
  bloodVolume() {
    this.health -= 1;
    if (this.health <= 0) this.remove();
  }

  move(code: DirectionType): void {
    // 碰撞检测
    if (this.forbidDirection === code) return;
    const item = this.isCollide(code);
    if (!item) {
    } else if (item instanceof TankProps) {
      item.effect(this);
    } else if (item instanceof StaticBlack) {
      // 判断是否碰撞静态方块
      this.forbidDirection = code;
      super.move(ReverseKey[code]);
      return;
    }
    super.move(code);
  }

  // 修改朝向
  orientation(direction: DirectionType) {
    let currentAngle = directionMap[this.direction];
    let targetAngle = directionMap[direction];
    let rotateAngle = targetAngle - currentAngle;
    if (rotateAngle > 180) {
      rotateAngle -= 360;
    } else if (rotateAngle <= -180) {
      rotateAngle += 360;
    }
    this.targter.rotateOf("center", rotateAngle);
    this.direction = direction;
  }

  #attackNo = function () {
    if (!this.status) return;
    let x = 0,
      y = 0;
    const bounds = new Bounds(this.targter.getBounds("box", "local"));
    const tarX = bounds.x;
    const tarY = bounds.y;
    switch (this.direction) {
      case "top":
        x = tarX + (this.targter.width || 0) / 2 - +Bullet.width / 2;
        y = tarY;
        break;
      case "down":
        x = tarX + (this.targter.width || 0) / 2 + Bullet.width / 2;
        y = tarY + (this.targter.height || 0) + 10;
        break;
      case "left":
        y = tarY + (this.targter.height || 0) / 2 + Bullet.width / 2;
        x = tarX;
        break;
      case "right":
        y = tarY + (this.targter.height || 0) / 2 - Bullet.width / 2;
        x = tarX + (this.targter.width || 0);
        break;
    }
    new Bullet({ x, y, direction: this.direction, ascriptionTankId: this.id });
  };

  // 发炮
  attack = throttle(this.#attackNo, this.#attackInterval);
  getAttackInterval = () => {
    return this.#attackInterval;
  };
  //AttackInterval 修改攻击间隔
  setAttackInterval = (value: number, time?: number) => {
    this.attack = throttle(this.#attackNo, value);
    if (time) {
      const item = this.stateProps.get("AttackInterval");
      if (item) {
        clearTimeout(item);
      }
      const t = setTimeout(() => {
        this.setAttackInterval(this.#attackInterval);
      }, time * 1000);
      this.stateProps.set("AttackInterval", t);
    }
  };
}
